<!--
  Copyright JS Foundation and other contributors, http://js.foundation

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<script type="text/x-red" data-template-name="http in">
    <div class="form-row">
        <label for="node-input-method"><i class="fa fa-tasks"></i> <span data-i18n="httpin.label.method"></span></label>
        <select type="text" id="node-input-method" style="width:70%;">
        <option value="get">GET</option>
        <option value="post">POST</option>
        <option value="put">PUT</option>
        <option value="delete">DELETE</option>
        <option value="patch">PATCH</option>
        </select>
    </div>
    <div class="form-row form-row-http-in-upload hide">
        <label>&nbsp;</label>
        <input type="checkbox" id="node-input-upload" style="display: inline-block; width: auto; vertical-align: top;">
        <label for="node-input-upload" style="width: 70%;" data-i18n="httpin.label.upload"></label>
    </div>
    <div class="form-row">
        <label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="httpin.label.url"></span></label>
        <input id="node-input-url" type="text" placeholder="/url">
    </div>
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
    </div>
    <div class="form-row row-swagger-doc">
        <label for="node-input-swaggerDoc"><i class="fa fa-file-text-o"></i> <span data-i18n="httpin.label.doc"></span></label>
        <input type="text" id="node-input-swaggerDoc">
    </div>
    <div id="node-input-tip" class="form-tips"><span data-i18n="httpin.tip.in"></span><code><span id="node-input-path"></span></code>.</div>
</script>

<script type="text/x-red" data-help-name="http in">
    <p>Creates an HTTP end-point for creating web services.</p>
    <h3>Outputs</h3>
    <dl class="message-properties">
        <dt>payload</dt>
        <dd>For a GET request, contains an object of any query string parameters.
            Otherwise, contains the body of the HTTP request.</dd>
        <dt>req<span class="property-type">object</span></dt>
        <dd>An HTTP request object. This object contains multiple properties that
            provide information about the request.
            <ul>
             <li><code>body</code> - the body of the incoming request. The format
                 will depend on the request.</li>
             <li><code>headers</code> - an object containing the HTTP request headers.</li>
             <li><code>query</code> - an object containing any query string parameters.</li>
             <li><code>params</code> - an object containing any route parameters.</li>
             <li><code>cookies</code> - an object containing the cookies for the request.</li>
             <li><code>files</code> - if enabled within the node, an object containing
                 any files uploaded as part of a POST request.</li>
            </ul>
        </dd>
        <dt>res<span class="property-type">object</span></dt>
        <dd>An HTTP response object. This property should not be used directly;
            the <code>HTTP Response</code> node documents how to respond to a request.
            This property must remain attached to the message passed to the response node.</dd>
    </dl>
    <h3>Details</h3>
    <p>The node will listen on the configured path for requests of a particular type.
       The path can be fully specified, such as <code>/user</code>, or include
       named parameters that accept any value, such as <code>/user/:name</code>.
       When named parameters are used, their actual value in a request can be accessed under `msg.req.params`.</p>
    <p>For requests that include a body, such as a POST or PUT, the contents of
       the request is made available as <code>msg.payload</code>.</p>
    <p>If the content type of the request can be determined, the body will be parsed to
       any appropriate type. For example, <code>application/json</code> will be parsed to
       its JavaScript object representation.</p>
    <p><b>Note:</b> this node does not send any response to the request. The flow
       must include an HTTP Response node to complete the request.</p>
</script>

<script type="text/x-red" data-template-name="http response">
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
        <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
    </div>
    <div class="form-row">
        <label for="node-input-statusCode"><i class="fa fa-long-arrow-left"></i> <span data-i18n="httpin.label.status"></span></label>
        <input type="text" id="node-input-statusCode" placeholder="msg.statusCode">
    </div>
    <div class="form-row" style="margin-bottom:0;">
        <label><i class="fa fa-list"></i> <span data-i18n="httpin.label.headers"></span></label>
    </div>
    <div class="form-row node-input-headers-container-row">
        <ol id="node-input-headers-container"></ol>
    </div>
    <div class="form-tips"><span data-i18n="[html]httpin.tip.res"></span></div>
</script>

<script type="text/x-red" data-help-name="http response">
    <p>Sends responses back to requests received from an HTTP Input node.</p>

    <h3>Inputs</h3>
    <dl class="message-properties">
        <dt>payload <span class="property-type">string</span></dt>
        <dd>The body of the response.</dd>
        <dt class="optional">statusCode <span class="property-type">number</span></dt>
        <dd>If set, this is used as the response status code. Default: 200.</dd>
        <dt class="optional">headers <span class="property-type">object</span></dt>
        <dd>If set, provides HTTP headers to include in the response.</dd>
        <dt class="optional">cookies <span class="property-type">object</span></dt>
        <dd>If set, can be used to set or delete cookies.</dd>
    </dl>
    <h3>Details</h3>
    <p>The <code>statusCode</code> and <code>headers</code> can also be set within
    the node itself. If a property is set within the node, it cannot be overridden
    by the corresponding message property.</p>
    <h4>Cookie handling</h4>
    <p>The <code>cookies</code> property must be an object of name/value pairs.
    The value can be either a string to set the value of the cookie with default
    options, or it can be an object of options.<p>
    <p>The following example sets two cookies - one called <code>name</code> with
    a value of <code>nick</code>, the other called <code>session</code> with a
    value of <code>1234</code> and an expiry set to 15 minutes.</p>
    <pre>
msg.cookies = {
    name: 'nick',
    session: {
        value: '1234',
        maxAge: 900000
    }
}</pre>
    <p>The valid options include:</p>
    <ul>
    <li><code>domain</code> - (String) domain name for the cookie</li>
    <li><code>expires</code> - (Date) expiry date in GMT. If not specified or set to 0, creates a session cookie</li>
    <li><code>maxAge</code> - (String) expiry date as relative to the current time in milliseconds</li>
    <li><code>path</code> - (String) path for the cookie. Defaults to /</li>
    <li><code>value</code> - (String) the value to use for the cookie</li>
    </ul>
    <p>To delete a cookie, set its <code>value</code> to <code>null</code>.</p>

</script>

<script type="text/javascript">
(function() {
    RED.nodes.registerType('http in',{
        category: 'input',
        color:"rgb(231, 231, 174)",
        defaults: {
            name: {value:""},
            url: {value:"",required:true},
            method: {value:"get",required:true},
            upload: {value:false},
            swaggerDoc: {type:"swagger-doc", required:false}
        },
        inputs:0,
        outputs:1,
        icon: "white-globe.png",
        label: function() {
            if (this.name) {
                return this.name;
            } else if (this.url) {
                var root = RED.settings.httpNodeRoot;
                if (root.slice(-1) != "/") {
                    root = root+"/";
                }
                if (this.url.charAt(0) == "/") {
                    root += this.url.slice(1);
                } else {
                    root += this.url;
                }
                return "["+this.method+"] "+root;
            } else {
                return "http";
            }
        },
        labelStyle: function() {
            return this.name?"node_label_italic":"";
        },
        oneditprepare: function() {
            var root = RED.settings.httpNodeRoot;
            if (root.slice(-1) == "/") {
                root = root.slice(0,-1);
            }
            if (root == "") {
                $("#node-input-tip").hide();
            } else {
                $("#node-input-path").html(root);
                $("#node-input-tip").show();
            }
            if(!RED.nodes.getType("swagger-doc")){
                $('.row-swagger-doc').hide();
            }
            $("#node-input-method").change(function() {
                if ($(this).val() === "post") {
                    $(".form-row-http-in-upload").show();
                } else {
                    $(".form-row-http-in-upload").hide();
                }
            }).change();


        }

    });
    var headerTypes = [
        {value:"content-type",label:"Content-Type",hasValue: false},
        {value:"location",label:"Location",hasValue: false},
        {value:"other",label:"other",icon:"red/images/typedInput/az.png"}
       ]
    var contentTypes = [
        {value:"application/json",label:"application/json",hasValue: false},
        {value:"application/xml",label:"application/xml",hasValue: false},
        {value:"text/css",label:"text/css",hasValue: false},
        {value:"text/html",label:"text/html",hasValue: false},
        {value:"text/plain",label:"text/plain",hasValue: false},
        {value:"image/gif",label:"image/gif",hasValue: false},
        {value:"image/png",label:"image/png",hasValue: false},
        {value:"other",label:"other",icon:"red/images/typedInput/az.png"}
    ];

    RED.nodes.registerType('http response',{
        category: 'output',
        color:"rgb(231, 231, 174)",
        defaults: {
            name: {value:""},
            statusCode: {value:"",validate: RED.validators.number(true)},
            headers: {value:{}}
        },
        inputs:1,
        outputs:0,
        align: "right",
        icon: "white-globe.png",
        label: function() {
            return this.name||("http"+(this.statusCode?" ("+this.statusCode+")":""));
        },
        labelStyle: function() {
            return this.name?"node_label_italic":"";
        },
        oneditprepare: function() {
            function resizeRule(rule) {
                var newWidth = rule.width();
                rule.find('.red-ui-typedInput').typedInput("width",(newWidth-15)/2);

            }
            var headerList = $("#node-input-headers-container").css('min-height','150px').css('min-width','450px').editableList({
                addItem: function(container,i,header) {
                    var row = $('<div/>').appendTo(container);
                    var propertyName = $('<input/>',{class:"node-input-header-name",type:"text"})
                        .appendTo(row)
                        .typedInput({types:headerTypes});

                    var propertyValue = $('<input/>',{class:"node-input-header-value",type:"text",style:"margin-left: 10px"})
                        .appendTo(row)
                        .typedInput({types:
                            header.h === 'content-type'?contentTypes:[{value:"other",label:"other",icon:"red/images/typedInput/az.png"}]
                        });

                    var matchedType = headerTypes.filter(function(ht) {
                        return ht.value === header.h
                    });
                    if (matchedType.length === 0) {
                        propertyName.typedInput('type','other');
                        propertyName.typedInput('value',header.h);
                        propertyValue.typedInput('value',header.v);
                    } else {
                        propertyName.typedInput('type',header.h);

                        if (header.h === "content-type") {
                            matchedType = contentTypes.filter(function(ct) {
                                return ct.value === header.v;
                            });
                            if (matchedType.length === 0) {
                                propertyValue.typedInput('type','other');
                                propertyValue.typedInput('value',header.v);
                            } else {
                                propertyValue.typedInput('type',header.v);
                            }
                        } else {
                            propertyValue.typedInput('value',header.v);
                        }
                    }

                    matchedType = headerTypes.filter(function(ht) {
                        return ht.value === header.h
                    });
                    if (matchedType.length === 0) {
                        propertyName.typedInput('type','other');
                        propertyName.typedInput('value',header.h);
                    } else {
                        propertyName.typedInput('type',header.h);
                    }

                    propertyName.on('change',function(event) {
                        var type = propertyName.typedInput('type');
                        if (type === 'content-type') {
                            propertyValue.typedInput('types',contentTypes);
                        } else {
                            propertyValue.typedInput('types',[{value:"other",label:"other",icon:"red/images/typedInput/az.png"}]);
                        }
                    });



                    resizeRule(container);
                },
                resizeItem: resizeRule,
                removable: true
            });

            if (this.headers) {
                for (var key in this.headers) {
                    if (this.headers.hasOwnProperty(key)) {
                        headerList.editableList('addItem',{h:key,v:this.headers[key]});
                    }
                }
            }
        },
        oneditsave: function() {
            var headers = $("#node-input-headers-container").editableList('items');
            var node = this;
            node.headers = {};
            headers.each(function(i) {
                var header = $(this);
                var keyType = header.find(".node-input-header-name").typedInput('type');
                var keyValue = header.find(".node-input-header-name").typedInput('value');
                var valueType = header.find(".node-input-header-value").typedInput('type');
                var valueValue = header.find(".node-input-header-value").typedInput('value');
                var key = keyType;
                var value = valueType;
                if (keyType === 'other') {
                    key = keyValue;
                }
                if (valueType === 'other') {
                    value = valueValue;
                }
                if (key !== '') {
                    node.headers[key] = value;
                }
            });
        },
        oneditresize: function(size) {
            var rows = $("#dialog-form>div:not(.node-input-headers-container-row)");
            var height = size.height;
            for (var i=0; i<rows.size(); i++) {
                height -= $(rows[i]).outerHeight(true);
            }
            var editorRow = $("#dialog-form>div.node-input-headers-container-row");
            height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));

            $("#node-input-headers-container").editableList('height',height);
        }
    });
})();
</script>
